home *** CD-ROM | disk | FTP | other *** search
/ MacTech 1 to 12 / MacTech-vol-1-12.toast / Source / MacTech® Magazine / Volume 10 - 1994 / 10.04 Apr 94 / Accurate Timing / TStats / TStats.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-02-13  |  8.4 KB  |  465 lines  |  [TEXT/KAHL]

  1. /* TStats --------------------------------------------------------
  2.  *
  3.  * Accumulate, calculate and display timing data.
  4.  *
  5.  * Copyright (c) 1993 Bill Karsh.
  6.  * All rights reserved.
  7.  *
  8.  */
  9.  
  10.  
  11. #pragma options( honor_register, !assign_registers )
  12. #pragma options( !check_ptrs )
  13.  
  14.  
  15. #include    "TStats.h"
  16. #include    "LongArrayStats.h"
  17. #include    "PlotLongArray.h"
  18. #include    <math.h>
  19. #include    <stdio.h>
  20.  
  21.  
  22. #define        WMargins        5
  23. #define        TitleBarHt        18
  24. #define        TextLines        3
  25. #define        UseSameScales    1
  26.  
  27. // glue and shorthands
  28.  
  29. #define        Alloc( type, n )                            \
  30.             (type*)NewPtr( sizeof(type) * (n) )
  31.             
  32. #define        Kill( q )                                    \
  33.             if( ts->q.data ) DisposePtr( ts->q.data )
  34.             
  35. #define        Limits( q )                                    \
  36.             LongArrayMinMax( ts->q.data, ts->q.N,        \
  37.             &ts->q.min, &ts->q.max )
  38.             
  39. #define        Plot( q, r, str )                            \
  40.             PlotLongArray( ts->q.data, ts->q.N,            \
  41.             0, ts->q.N,    ts->q.min, ts->q.max,            \
  42.             &ts->r, str )
  43.             
  44. #define        Histo( h, q )                                \
  45.             LongArrayBin( ts->q.data, ts->q.N,            \
  46.             ts->q.min, ts->q.max,                        \
  47.             ts->h.data, ts->h.N )
  48.  
  49. #define        SameScales( u, v )                            \
  50.             if( ts->u.min < ts->v.min )                    \
  51.                 ts->v.min = ts->u.min;                    \
  52.             else                                        \
  53.                 ts->u.min = ts->v.min;                    \
  54.                                                         \
  55.             if( ts->u.max > ts->v.max )                    \
  56.                 ts->v.max = ts->u.max;                    \
  57.             else                                        \
  58.                 ts->u.max = ts->v.max;
  59.                 
  60.             
  61. #define        MaxBin( q, h, w )                            \
  62.             LongArrayGetMaxBin( ts->q.data, ts->q.N,    \
  63.             ts->q.min, ts->q.max,                        \
  64.             ts->h.data, ts->h.N,                        \
  65.             ts->w.data, &ts->w.N )
  66.             
  67. #define        NewPort()                                    \
  68.             GetPort( &oldPort ); SetPort( ts->w )
  69.                         
  70. #define        Print( h, str, val, dig )                    \
  71.             MoveTo( h, v );                                \
  72.             *s = sprintf( s+1, "%."#dig"f", val );        \
  73.             DrawString( str ); DrawString( s )
  74.  
  75.             
  76. static pTS    gTS;
  77.  
  78.  
  79.  
  80.  
  81.  
  82.  
  83. /* LayoutWindow --------------------------------------------------
  84.  *
  85.  * Arrange data areas of window.
  86.  *
  87.  */
  88.  
  89. static void LayoutWindow( void )
  90. {
  91.     register pTS    ts = gTS;
  92.     Rect            r;
  93.     FontInfo        fi;
  94.     short            lineHt, pad;
  95.  
  96.     r = ts->w->portRect;
  97.     InsetRect( &r, WMargins, WMargins );
  98.  
  99.     GetFontInfo( &fi );
  100.     lineHt = fi.ascent + fi.descent + fi.leading;
  101.  
  102. #define    t1 ts->statsR1
  103. #define    t2 ts->statsR2
  104. #define    p1 ts->plotR1
  105. #define    p2 ts->plotR2
  106.  
  107. // left and right
  108.  
  109.     t1.left  = p1.left  = p2.left  = r.left;
  110.     t2.right = p1.right = p2.right = r.right;
  111.  
  112.     t1.right = t1.left  + (r.right - t1.left - WMargins)/2;
  113.     t2.left  = t1.right + WMargins;
  114.  
  115. // top and bottom
  116.  
  117.     t1.top    = t2.top    = r.top;
  118.     t1.bottom = t2.bottom = t1.top + TextLines * lineHt + 2;
  119.         
  120.     p1.top    = t1.bottom + WMargins;
  121.     p1.bottom = p1.top + (r.bottom - p1.top - WMargins)/2;
  122.     
  123.     p2.top    = p1.bottom + WMargins;
  124.     p2.bottom = r.bottom;
  125.  
  126. #undef t1
  127. #undef t2
  128. #undef p1
  129. #undef p2
  130. }
  131.  
  132.  
  133. /* AllocateArrays ------------------------------------------------
  134.  *
  135.  * Allocate data arrays.
  136.  *
  137.  */
  138.  
  139. static void AllocateArrays( long nData, long nBins )
  140. {
  141.     register pTS    ts = gTS;
  142.     
  143.     ts->maxRaw  = nData;
  144.     ts->bins1.N    = ts->bins2.N = nBins;
  145.     
  146.     ts->acc1 = ts->raw1.data = Alloc( long, nData );
  147.     ts->acc2 = ts->raw2.data = Alloc( long, nData );
  148.         
  149.     ts->bins1.data = Alloc( long, nBins+1 );
  150.     ts->bins2.data = Alloc( long, nBins+1 );
  151.     
  152.     ts->work1.data = ts->work2.data = nil;
  153.     
  154.     ts->raw1.N = ts->raw2.N = 0;
  155. }
  156.  
  157.  
  158. /* TSInit --------------------------------------------------------
  159.  *
  160.  * Allocate window and init structures.
  161.  *
  162.  */
  163.  
  164. void TSInit( Rect *rGlobal, long nData, long nBins )
  165. {
  166.     register pTS    ts;
  167.     GrafPtr            oldPort;
  168.     Rect            *r, R;
  169.     
  170.     gTS = ts = Alloc( TSRec, 1 );
  171.     
  172.     if( !(r = rGlobal) ) {    // auto size window
  173.         R = screenBits.bounds;
  174.         InsetRect( &R, 3, 3 );
  175.         R.top += MBarHeight + TitleBarHt;
  176.         R.bottom >>= 1;
  177.         r = &R;
  178.     }
  179.     
  180.     ts->w = NewWindow( nil, r, nil, true,
  181.             noGrowDocProc, (WindowPtr)-1, false, 0L );
  182.             
  183.     NewPort();
  184.     TextFont( geneva );
  185.     TextSize( 9 );
  186.     
  187.     LayoutWindow();
  188.     
  189.     AllocateArrays( nData, nBins );
  190.     
  191.     ts->combRawSd = 0.0;
  192.     
  193.     SetPort( oldPort );
  194. }
  195.  
  196.  
  197. /* TSDispose -----------------------------------------------------
  198.  *
  199.  * Deallocate.
  200.  *
  201.  */
  202.  
  203. void TSDispose( void )
  204. {
  205.     register pTS    ts = gTS;
  206.     
  207.     if( !ts ) return;
  208.     
  209.     if( ts->w ) DisposeWindow( ts->w );
  210.     
  211.     Kill( raw1 );
  212.     Kill( raw2 );
  213.     Kill( work1 );
  214.     Kill( work2 );
  215.     Kill( bins1 );
  216.     Kill( bins2 );
  217.         
  218.     DisposePtr( ts );
  219. }
  220.  
  221.  
  222. /* TSAccumulate --------------------------------------------------
  223.  *
  224.  * Add data to arrays.
  225.  *
  226.  */
  227.  
  228. void TSAccumulate( long time1, long time2 )
  229. {
  230.     register pTS    ts = gTS;
  231.  
  232.     if( ts->raw1.N < ts->maxRaw && time1 >= 0 ) {
  233.         *ts->acc1++ = time1;
  234.         ++ts->raw1.N;
  235.     }
  236.     
  237.     if( ts->raw2.N < ts->maxRaw && time2 >= 0 ) {
  238.         *ts->acc2++ = time2;
  239.         ++ts->raw2.N;
  240.     }
  241. }
  242.  
  243.  
  244. /* TSRawPlots ----------------------------------------------------
  245.  *
  246.  * Display plots of accumulated raw data.
  247.  *
  248.  */
  249.  
  250. void TSRawPlots( void )
  251. {
  252.     register pTS    ts = gTS;
  253.     GrafPtr            oldPort;
  254.     
  255.     if( !ts->raw1.N ) return;
  256.     
  257.     NewPort();
  258.     
  259.     Limits( raw1 );
  260.     Limits( raw2 );
  261.     
  262. #if UseSameScales == 1
  263.     SameScales( raw1, raw2 );
  264. #endif
  265.     
  266.     Plot( raw1, plotR1, "\pRaw Time1" );
  267.     Plot( raw2, plotR2, "\pRaw Time2" );
  268.         
  269.     SetPort( oldPort );
  270. }
  271.  
  272.  
  273. /* TSStats -------------------------------------------------------
  274.  *
  275.  * Calculate and display statistics for arrays.
  276.  *
  277.  * sourceType is one of the defined constants {kRaw, kWork}.
  278.  *
  279.  */
  280.  
  281. void TSStats( long sourceType )
  282. {
  283.     register pTS    ts = gTS;
  284.     GrafPtr            oldPort;
  285.     Rect            *r;
  286.     double            mean1, mean2, sd1, sd2, z1, z2;
  287.     long            *data1, *data2;
  288.     long            N1, N2;
  289.     FontInfo        fi;
  290.     Byte            s[36];
  291.     short            lineHt, h1, h2, h3, v;
  292.     
  293.     if( sourceType == kRaw ) {
  294.         data1 = ts->raw1.data;
  295.         data2 = ts->raw2.data;
  296.         N1 = ts->raw1.N;
  297.         N2 = ts->raw2.N;
  298.         r = &ts->statsR1;
  299.     }
  300.     else {
  301.         data1 = ts->work1.data;
  302.         data2 = ts->work2.data;
  303.         N1 = ts->work1.N;
  304.         N2 = ts->work2.N;
  305.         r = &ts->statsR2;
  306.     }
  307.     
  308.     if( !N1 ) return;
  309.         
  310.     NewPort();
  311.     
  312.     ForeColor( blackColor );
  313.     EraseRect( r );
  314.     FrameRect( r );
  315.     
  316.     GetFontInfo( &fi );
  317.     h1 = r->left + 2;
  318.     h3 = (r->right - r->left)/3;
  319.     h2 = r->left + h3;
  320.     h3 += h2;
  321.     v  = r->top + fi.ascent + 1;
  322.     
  323.     lineHt = fi.ascent + fi.descent + fi.leading;
  324.     
  325.     LongArrayMeanDev( data1, N1, &mean1, &sd1 );
  326.     LongArrayMeanDev( data2, N2, &mean2, &sd2 );
  327.         
  328.     if( sourceType == kRaw ) {
  329.         Print( h1, "\pmean1 = ", mean1, 0 );
  330.         Print( h2, "\pmean2 = ", mean2, 0 );
  331.     }
  332.     else {
  333.         Print( h1, "\pmode1 = ", mean1, 0 );
  334.         Print( h2, "\pmode2 = ", mean2, 0 );
  335.     }
  336.     
  337.     v += lineHt;
  338.     
  339.     Print( h1, "\psd1 = ", sd1, 2 );
  340.     Print( h2, "\psd2 = ", sd2, 2 );
  341.     
  342.     v += lineHt;
  343.     
  344.     z1 = mean1 - mean2;
  345.     Print( h1, "\pdiff = ", z1, 0 );
  346.     
  347.     z2 = z1 / mean2 * 100.0;
  348.     Print( h2, "\prel diff = ", z2, 2 );
  349.     DrawChar( '%' );
  350.     
  351.     if( sourceType == kRaw ) {
  352.     
  353.         ts->combRawSd = z2 =
  354.             sqrt( sd1*sd1/ts->raw1.N + sd2*sd2/ts->raw2.N );
  355.             
  356.         if( z2 > 0.0 )
  357.             z1 = fabs( z1 ) / z2;
  358.         else
  359.             z1 = 0.0;
  360.         Print( h3, "\pZ = ", z1, 2 );
  361.     }
  362.     else {
  363.         if( ts->combRawSd > 0.0 )
  364.             z1 = fabs( z1 ) / ts->combRawSd;
  365.         else
  366.             z1 = 0.0;
  367.         Print( h3, "\pZ = ", z1, 2 );
  368.     }
  369.     
  370.     SetPort( oldPort );
  371. }
  372.  
  373.  
  374. /* TSRawHistos ---------------------------------------------------
  375.  *
  376.  * Calculate and display plots of freq data.
  377.  *
  378.  */
  379.  
  380. void TSRawHistos( void )
  381. {
  382.     register pTS    ts = gTS;
  383.     GrafPtr            oldPort;
  384.  
  385.     if( !ts->raw1.N ) return;
  386.     
  387.     NewPort();
  388.     
  389.     Histo( bins1, raw1 );
  390.     Histo( bins2, raw2 );
  391.     
  392.     Limits( bins1 );
  393.     Limits( bins2 );
  394.     
  395. #if UseSameScales == 1
  396.     SameScales( bins1, bins2 );
  397. #endif
  398.  
  399.     Plot( bins1, plotR1, "\pFreq Time1" );
  400.     Plot( bins2, plotR2, "\pFreq Time2" );
  401.     
  402.     SetPort( oldPort );
  403. }
  404.  
  405.  
  406. /* TSFilterMode --------------------------------------------------
  407.  *
  408.  * Calculate and display plots of data only in
  409.  * max bin ( the mode ).
  410.  * Places this separated data in work structures.
  411.  *
  412.  * sourceType is one of the defined constants {kRaw, kWork}.
  413.  *
  414.  * Returns true if max == min for newly filtered data,
  415.  * else returns false.
  416.  *
  417.  */
  418.  
  419. Boolean TSFilterMode( long sourceType )
  420. {
  421.     register pTS    ts = gTS;
  422.     GrafPtr            oldPort;
  423.     
  424.     if( !ts->raw1.N ) return true;
  425.     
  426.     NewPort();
  427.     
  428.     if( !ts->work1.data )
  429.         ts->work1.data = Alloc( long, ts->raw1.N );
  430.         
  431.     if( !ts->work2.data )
  432.         ts->work2.data = Alloc( long, ts->raw1.N );
  433.         
  434.     if( sourceType == kRaw ) {
  435.         MaxBin( raw1, bins1, work1 );
  436.         MaxBin( raw2, bins2, work2 );
  437.     }
  438.     else {
  439.         if( ts->work1.max != ts->work1.min )
  440.             MaxBin( work1, bins1, work1 );
  441.             
  442.         if( ts->work2.max != ts->work2.min )
  443.             MaxBin( work2, bins2, work2 );
  444.     }
  445.         
  446.     Limits( work1 );
  447.     Limits( work2 );
  448.     
  449.     Histo( bins1, work1 );
  450.     Histo( bins2, work2 );
  451.     
  452.     Limits( bins1 );
  453.     Limits( bins2 );
  454.     
  455.     Plot( bins1, plotR1, "\pMost Freq Time1" );
  456.     Plot( bins2, plotR2, "\pMost Freq Time2" );
  457.         
  458.     SetPort( oldPort );
  459.     
  460.     return (ts->work1.max == ts->work1.min &&
  461.             ts->work2.max == ts->work2.min);
  462. }
  463.  
  464.  
  465.